package com.cyanite.playlv2;

import com.cyanite.playlv2.util.NotificationsUtil;
import com.cyanite.playlv2.util.RemoteResourceManager;
import com.cyanite.playlv2.widget.PhotoAdapter;
import com.cyanite.playlv2api.types.Group;
import com.cyanite.playlv2api.types.Photo;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.Gallery;
import android.widget.ImageSwitcher;
import android.widget.ImageView;
import android.widget.ViewSwitcher;
import android.widget.Gallery.LayoutParams;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;

public class TripPhotosActivity extends Activity implements
    AdapterView.OnItemSelectedListener, ViewSwitcher.ViewFactory {

    public static final String EXTRA_TRIP_ID = PlayLv2.PACKAGE_NAME
        + ".TripPhotosActivity.EXTRA_TRIP_ID";

    private ImageSwitcher mImgSwitcher;
    private Gallery mGallery;
    private View mViewProgressBar;
    private RemoteResourceManager mRrm;
    private RemoteResourceManagerObserver mResourcesObserver;
    private Handler mHandler;
    private StateHolder mStateHolder;

    private BroadcastReceiver mLoggedOutReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            finish();
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.trip_photos_activity);
        registerReceiver(mLoggedOutReceiver, new IntentFilter(PlayLv2.INTENT_ACTION_LOGGED_OUT));

        mHandler = new Handler();
        mRrm = ((PlayLv2) getApplication()).getRemoteResourceManager();
        mResourcesObserver = new RemoteResourceManagerObserver();
        mRrm.addObserver(mResourcesObserver);

        mStateHolder = new StateHolder();
        String tripId =  "";
        if (getIntent().hasExtra(EXTRA_TRIP_ID)) {
            tripId = getIntent().getExtras().getString(EXTRA_TRIP_ID);          
        }   else {
            finish();
            return;
        }
        mStateHolder.startTaskTripPhotos(TripPhotosActivity.this, tripId);
        ensureUi();
    }

    @Override
    public void onPause() {
        super.onPause();

        if (isFinishing()) {
            mStateHolder.cancelTasks();
            mHandler.removeCallbacks(mRunnableUpdateTripPhoto);
            mRrm.deleteObserver(mResourcesObserver);
            unregisterReceiver(mLoggedOutReceiver);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public void onItemSelected(AdapterView parent, View v, int position, long id) {
        mImgSwitcher.setImageDrawable(new BitmapDrawable(mStateHolder.getBmp(position)));
    }

    @SuppressWarnings("unchecked")
    @Override
    public void onNothingSelected(AdapterView parent) {
    }

    @Override
    public View makeView() {
        ImageView imgView = new ImageView(this);
        imgView.setBackgroundColor(0xFF000000);
        imgView.setScaleType(ImageView.ScaleType.FIT_CENTER);
        imgView.setLayoutParams(new ImageSwitcher.LayoutParams(LayoutParams.FILL_PARENT,
                LayoutParams.FILL_PARENT));
        return imgView;
    }

    private void ensureUi() {
        setTitle(getString(R.string.trip_photos_activity_label));
        mViewProgressBar = findViewById(R.id.tripPhotosProgress);
        mViewProgressBar.setVisibility(View.VISIBLE);
        mGallery = (Gallery) findViewById(R.id.gallery);
        mGallery.setVisibility(View.GONE);

        if (mStateHolder.getPhotos() != null && mStateHolder.getPhotos().size() > 0)    {
            mGallery.setVisibility(View.VISIBLE);
            mImgSwitcher = (ImageSwitcher) findViewById(R.id.switcher);
            mImgSwitcher.setFactory(this);
            mImgSwitcher.setInAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_in));
            mImgSwitcher.setOutAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_out));            
            ensureUiPhotos();
        }
    }

    private void ensureUiPhotos()    {
        if (mStateHolder.getBmps().size() < mStateHolder.getPhotos().size() )    {
            for (Photo it : mStateHolder.getPhotos()) {
                Uri uriPhoto = Uri.parse(it.getPhotoUrl());
                if (mRrm.exists(uriPhoto)) {
                    try {
                        Bitmap bitmap = BitmapFactory.decodeStream(mRrm.getInputStream(uriPhoto));
                        mStateHolder.addBitmap(bitmap);
                    } catch (IOException ex) {
                        mImgSwitcher.setImageResource(R.drawable.trip_default_photo);
                    }
                }   else {
                    mRrm.request(uriPhoto);
                    mImgSwitcher.setImageResource(R.drawable.trip_default_photo);
                }
            }
            if (mStateHolder.getBmps().size() >= mStateHolder.getPhotos().size())  {
                setProgressBarIndeterminateVisibility(false);
            } else {
                setProgressBarIndeterminateVisibility(true);
            }
            mHandler.removeCallbacks(mRunnableUpdateTripPhoto);
        }
        mGallery.setAdapter(new PhotoAdapter(this, mStateHolder.getBmps()));
        mGallery.setOnItemSelectedListener(this);
        mGallery.postInvalidate();
        mImgSwitcher.postInvalidate();
    }

    private class RemoteResourceManagerObserver implements Observer {
        @Override
        public void update(Observable observable, Object data) {
            mHandler.post(mRunnableUpdateTripPhoto);
        }
    }

    private Runnable mRunnableUpdateTripPhoto = new Runnable() {

        @Override
        public void run() {
            ensureUiPhotos();
        }
    };

    private void onTripPhotosTaskComplete(Group<Photo> photos, Exception ex) {        
        mViewProgressBar.setVisibility(View.GONE);
        if (photos != null && photos.size() > 0) {
            mStateHolder.setPhotos(photos);
            ensureUi();
        } else if (ex != null) {
            NotificationsUtil.ToastReasonForFailure(this, ex);
        }
    }

    private static class TripPhotosTask extends AsyncTask<Void, Void, Group<Photo>> {

        private TripPhotosActivity mActivity;
        private String mTripId;
        private Exception mReason;

        public TripPhotosTask(TripPhotosActivity activity, String tripId) {
            mTripId = tripId;
            mActivity = activity;
        }

        @Override
        protected void onPreExecute() {
        }

        @Override
        protected Group<Photo> doInBackground(Void... params) {
            try {
                return ((PlayLv2) mActivity.getApplication()).getPlayLv2Api().tripPhotos(mTripId);
            } catch (Exception ex) {
                mReason = ex;
                return null;
            }
        }

        @Override
        protected void onPostExecute(Group<Photo> photos) {
            if (mActivity != null) {
                mActivity.onTripPhotosTaskComplete(photos, mReason);
            }
        }

        @Override
        protected void onCancelled() {
            if (mActivity != null) {
                mActivity.onTripPhotosTaskComplete(null, mReason);
            }
        }

        public void setActivity(TripPhotosActivity activity) {
            mActivity = activity;
        }
    }

    private static class StateHolder {

        private Group<Photo> mPhotos;
        private ArrayList<Bitmap> mBmps;
        private TripPhotosTask mTripPhotosTask;

        public StateHolder() {
            mBmps = new ArrayList<Bitmap>();
        }

        public Bitmap getBmp(int position)   {
            return mBmps.get(position);
        }

        public void addBitmap(Bitmap bmp)    {
            mBmps.add(bmp);
        }

        public ArrayList<Bitmap> getBmps()   {
            return mBmps;
        }

        public void startTaskTripPhotos(TripPhotosActivity activity, String tripId) {
            mTripPhotosTask = new TripPhotosTask(activity, tripId);
            mTripPhotosTask.execute();
        }

        public void setPhotos(Group<Photo> photos)    {
            mPhotos = photos;
        }

        public Group<Photo> getPhotos()    {
            return mPhotos;
        }

        public void cancelTasks() {
            if (mTripPhotosTask != null) {
                mTripPhotosTask.setActivity(null);
                mTripPhotosTask.cancel(true);
            }
        }
    }

}